var UP_RAW_VERSION = 0x00;
var UP_RAW_CMD = 0x00;
var DOWN_RAW_VERSION = 0x00;
var DOWN_RAW_CMD = 0x80;
var RAW_HEAD = 0xaa;

var ALINK_VERSION = '1.0';
var METHOD_GET_CMD = 0x00, METHOD_GET_STR = 'thing.service.property.get';
var METHOD_SET_CMD = 0x01, METHOD_SET_STR = 'thing.service.property.set';
var METHOD_SERVICE_CMD = 0x02/*, METHOD_SERVICE_STR = 'SERVICE'*/;

var METHOD_REPORT_CMD = 0x80, METHOD_REPORT_STR = 'thing.event.property.post';
var METHOD_EVENT_CMD = 0x81;

var METHOD_ACK_CMD = 0xFF, METHOD_ACK_STR = 'ACK';

var structStartId = 30;
var PP_TYPE = {
	PROTOCOL_PROP_TYPE_BOOL: 0,
	PROTOCOL_PROP_TYPE_INT8: 1,
	PROTOCOL_PROP_TYPE_UINT8: 2,
	PROTOCOL_PROP_TYPE_INT16: 3,
	PROTOCOL_PROP_TYPE_UINT16: 4,
	PROTOCOL_PROP_TYPE_INT32: 5,
	PROTOCOL_PROP_TYPE_UINT32: 6,
	PROTOCOL_PROP_TYPE_INT64: 7,
	PROTOCOL_PROP_TYPE_UINT64: 8,
	PROTOCOL_PROP_TYPE_FLOAT32: 9, 
	PROTOCOL_PROP_TYPE_FLOAT64: 10,
	PROTOCOL_PROP_TYPE_STRING: 11,
	PROTOCOL_PROP_TYPE_DATE: 12,

};

var g_attrAry = ["PowerSwitch","WIFI_Band","WiFI_RSSI","WIFI_AP_BSSID","WIFI_Channel","WiFI_SNR"];
var g_attrTypeMap = {
   PowerSwitch:{protocolType:PP_TYPE.PROTOCOL_PROP_TYPE_BOOL, attrID:0, precise:null, v2s:false},
   WIFI_Band:{protocolType:PP_TYPE.PROTOCOL_PROP_TYPE_STRING, attrID:1, precise:null, v2s:false},
   WiFI_RSSI:{protocolType:PP_TYPE.PROTOCOL_PROP_TYPE_INT8, attrID:2, precise:null, v2s:false},
   WIFI_AP_BSSID:{protocolType:PP_TYPE.PROTOCOL_PROP_TYPE_STRING, attrID:3, precise:null, v2s:false},
   WIFI_Channel:{protocolType:PP_TYPE.PROTOCOL_PROP_TYPE_UINT8, attrID:4, precise:null, v2s:false},
   WiFI_SNR:{protocolType:PP_TYPE.PROTOCOL_PROP_TYPE_INT8, attrID:5, precise:null, v2s:false}
};

var g_serviceArray = [];
var g_serviceDataMap = {
	
};

var g_eventArray = ["thing.event.Error.post"];
var g_eventDataMap = {
	"thing.event.Error.post":{
        eventID:0,
        outputData:{
            ErrorCode:{protocolType:PP_TYPE.PROTOCOL_PROP_TYPE_UINT8, precise:null, v2s:false}
        },
        outputArray:["ErrorCode"]
      },
    
};

var g_structArray = [];
var g_structDataMap = {
	
};

function protocolToRawData(json)
{
	log('------------------------ protocolToRawData start ------------------------');
	var params = json['params'];
	var method = json['method'];
	var id = json['id'];
	var attrID = 0, v, string = '', charList = '', type = 0;

	var payloadArray = [];
	if (method == METHOD_GET_STR)
	{
		payloadArray.push(METHOD_GET_CMD); // GET BYTE -> 0x01
		payloadArray = payloadArray.concat(buffer_uint32(id)); // ID UINT32 -> id
		for (var i = 0; i < params.length; i++) {
			attrID = g_attrTypeMap[params[i]].attrID;
			payloadArray.push(attrID);
			log(params[i] + " " + attrID);
		}
	}
	else if (method == METHOD_SET_STR)
	{
		payloadArray.push(METHOD_SET_CMD); //payload cmd
		payloadArray = payloadArray.concat(buffer_uint32(id)); // ID UINT32 -> id
		for (var key in params)
		{
			type = g_attrTypeMap[key].protocolType;
			attrID = g_attrTypeMap[key].attrID;
			if (type >= structStartId)
			{
				var strVal = [];
				var strJson = params[key];
				var structMemb = g_structDataMap[key];
				var itemData = structMemb.item;
				var itemArray = structMemb.itemArray;
				for (var i = 0; i < itemArray.length; i++) 
				{
					var elemName = itemArray[i];
					var item = itemData[elemName];
					var ptype = item.protocolType;

					/* string固定字节 */
					if (ptype == PP_TYPE.PROTOCOL_PROP_TYPE_STRING)
					{
						string = unescape(encodeURIComponent(strJson[elemName]));
						charList = string.split('');
						var uint8Arrays = [];
						for (var j = 0; j < charList.length; j++) 
						{
							uint8Arrays.push(charList[j].charCodeAt(0));
						}

						for (; j < item.size; j++)
						{
							uint8Arrays.push(0);
						}

						strVal = strVal.concat(uint8Arrays);
					}
					else
					{
						v = buffer_dynamic(strJson[elemName], ptype);
						// log(elemName + " : " + typeof(strJson[elemName]) + " " + strJson[elemName]);
						// log(ptype + " " + attrID + " " + v.toString('hex'));
						strVal = strVal.concat(v);
					}
				}
				
				payloadArray.push(type);
				payloadArray.push(attrID);
				payloadArray = payloadArray.concat(strVal);
				continue;
			}

			v = buffer_dynamic(params[key], type);
			log(key + " : " + typeof(params[key]) + " " + params[key]);
			log(type + " " + attrID + " 0x" + v.toString('hex'));

			payloadArray.push(type);
			payloadArray.push(attrID);
            payloadArray = payloadArray.concat(v);
		}
	}
	else if (method == METHOD_ACK_STR)
	{
		payloadArray.push(METHOD_ACK_CMD); //payload cmd
		payloadArray = payloadArray.concat(buffer_uint32(id)); // ID UINT32 -> id
		var errorcode = params['errorcode'];
		payloadArray.push(errorcode);
	}
	else if (g_serviceDataMap.hasOwnProperty(method))
	{
		payloadArray.push(METHOD_SERVICE_CMD); //payload cmd
		payloadArray = payloadArray.concat(buffer_uint32(id)); // ID UINT32 -> id
		var serviceName = method;
		var inputData = params;
		var serviceItem = g_serviceDataMap[serviceName];
		payloadArray.push(serviceItem.serviceID);
		for (var key in serviceItem.inputArray)
		{
			var strval = [];
			var inputparamName = serviceItem.inputArray[key];
			type = serviceItem.inputData[inputparamName].protocolType;
			if (type == PP_TYPE.PROTOCOL_PROP_TYPE_STRING)
			{
				string = unescape(encodeURIComponent(inputData[inputparamName]));
			    charList = string.split('');
				var uint8Array = [];
				for (var j = 0; j < charList.length; j++) 
				{
					uint8Array.push(charList[j].charCodeAt(0));
				}

				for (; j < serviceItem.inputData[inputparamName].size; j++)
				{
					uint8Array.push(0);
				}

				strval = strval.concat(uint8Array);
			}
			else
			{
				var value = buffer_dynamic(inputData[inputparamName], type);
				log(key + " : " + inputparamName + " " + inputData[inputparamName]);
				log(type + " " + " 0x" + value.toString('hex'));
				strval = strval.concat(value);
			}

			payloadArray = payloadArray.concat(strval);
		}
	}
	else
	{
		//do nothing
		return;
	}

   	log("payloadArray data " + payloadArray.toString('hex'));

    var retBuffer = new Uint8Array(1 + 2 + 1 + 1 + payloadArray.length + 1);  //head length ver cmd payload checksum
    var dv = new DataView(retBuffer.buffer, 0);
    retBuffer[0] = RAW_HEAD; //head
    dv.setUint16(1, 1 + 1 + payloadArray.length + 1); // length -> ver cmd payload checksum
    retBuffer[3] = DOWN_RAW_VERSION; //ver
    retBuffer[4] = DOWN_RAW_CMD; //cmd
    for (var i = 0; i < payloadArray.length; i++)
    {
        retBuffer[i + 5] = payloadArray[i];
    }

	var checksum = 0;
	for (var i = 0; i < retBuffer.length - 1; i++) {
		checksum += retBuffer[i];
	}
	retBuffer[retBuffer.length - 1] = checksum & 0xff;
	log("return rawdata" + retBuffer.toString('hex'));

	log('------------------------ protocolToRawData end ------------------------');
	return [].slice.call(retBuffer);
}

function rawDataToProtocol(bytes)
{
    log('------------------------ rawDataToProtocol start ------------------------');

    var checksum = 0, itype = 0;
    var buffer = new Uint8Array(bytes.length);
    for (var i = 0; i < bytes.length; i++)
    {
        buffer[i] = bytes[i] & 0xff;
        if (i < bytes.length - 1)
            checksum += buffer[i];
    }
	checksum &= 0xff;

    var dv = new DataView(buffer.buffer, 0);
    var c_head = buffer[0];
    var c_length = dv.getInt16(1) + 3;
    var c_ver = buffer[3];
    var c_cmd = buffer[4];
    var c_checksum = buffer[buffer.length - 1];

	if (c_head != RAW_HEAD || checksum != c_checksum)
	{
		log('data check error ->  head : ' + c_head + " checksum : " + checksum + " " + c_checksum);
		return null;
	}

	//decode payload
	var jsonMap = new Object();

	var c_method = buffer[5];
	var c_id = dv.getUint32(6);

	var offset = 10; //payload data域
	if (c_method == METHOD_GET_CMD) //GET
	{
		jsonMap['method'] = METHOD_REPORT_STR;
		var bStop = false;
		var params = {};
		var loop = c_length;
		while(!bStop && loop) 
		{
			var payloadObj = type_dynamic(buffer, dv, offset);
			params[g_attrAry[payloadObj.attrID]] = payloadObj.value;
			offset += payloadObj.length;
			bStop = (offset >= (c_length - 1));
			loop--;
		}

		if (loop == 0)
		{
			log('data input err.');
			return null;
		}

		jsonMap['params'] = params;
		//jsonMap['code'] = 200;
	}
	else if (c_method == METHOD_REPORT_CMD)  //report
	{
		jsonMap['method'] = METHOD_REPORT_STR;
		var bStop = false;
		var params = {};
		var loop = c_length;
		while(!bStop && loop)
		{
			var payloadObj = type_dynamic(buffer, dv, offset);
			params[g_attrAry[payloadObj.attrID]] = payloadObj.value;
			offset += payloadObj.length;
			bStop = (offset >= (c_length - 1));
			loop--;
		}

		if (loop == 0)
		{
			log('data input err');
			return null;
		}

		jsonMap['params'] = params;
	}
	else if (c_method == METHOD_ACK_CMD) //ack
	{
		// jsonMap['method'] = METHOD_ACK_STR;
		// var ec = buffer[offset];
		// jsonMap['data'] = {"errorcode":ec};
		return null;
	}
	else if (c_method == METHOD_SERVICE_CMD)//service
	{
		var serviceID = buffer[offset++];
		var serviceName = g_serviceArray[serviceID];
		var serviceItem = g_serviceDataMap[serviceName];
		var outputData = serviceItem.outputData;
		var outputArray = serviceItem.outputArray;

		var outputDataJson = {};
		for (var i = 0; i < outputArray.length; i++) 
		{
			var itemName = outputArray[i];
			var item = outputData[itemName];
			itype = item.protocolType;
			if (itype == PP_TYPE.PROTOCOL_PROP_TYPE_STRING)
			{
				var string_v = type_string(buffer, offset, item.size);
				outputDataJson[itemName] = string_v.value;
				offset += item.size;
			}
			else
			{
				var payloadObj = type_dynamic_with_param(buffer, dv, offset, itype, item.precise);
				offset += payloadObj.length;
				if (item.v2s)
				{
					outputDataJson[itemName] = payloadObj.value.toString();
				}
				else if (itype >= PP_TYPE.PROTOCOL_PROP_TYPE_BOOL && itype <= PP_TYPE.PROTOCOL_PROP_TYPE_UINT64)
				{
					outputDataJson[itemName] = parseInt(payloadObj.value.toString());
				}
				else
				{
					outputDataJson[itemName] = payloadObj.value;
				}
			}
		}

		jsonMap['method'] = serviceName;
		jsonMap['params'] = outputDataJson;
	}
	else if (c_method == METHOD_EVENT_CMD)
	{
		var evntID = buffer[offset++];
		var eventName = g_eventArray[evntID];
		var eventItem = g_eventDataMap[eventName];
		var outputData = eventItem.outputData;
		var outputArray = eventItem.outputArray;

		var outputDataJson = {};
		for (var i = 0; i < outputArray.length; i++) 
		{
			var itemName = outputArray[i];
			var item = outputData[itemName];
			itype = item.protocolType;
			if (itype == PP_TYPE.PROTOCOL_PROP_TYPE_STRING)
			{
				var string_v = type_string(buffer, offset, item.size);
				outputDataJson[itemName] = string_v.value;
				offset += item.size;
			}
			else
			{
				var payloadObj = type_dynamic_with_param(buffer, dv, offset, itype, item.precise);
				offset += payloadObj.length;
				if (item.v2s)
				{
					outputDataJson[itemName] = payloadObj.value.toString();
				}
				else if (itype >= PP_TYPE.PROTOCOL_PROP_TYPE_BOOL && itype <= PP_TYPE.PROTOCOL_PROP_TYPE_UINT64)
				{
					outputDataJson[itemName] = parseInt(payloadObj.value.toString());
				}
				else
				{
					outputDataJson[itemName] = payloadObj.value;
				}
			}
		}

		jsonMap['method'] = eventName;
		jsonMap['params'] = outputDataJson;
	}
	else
	{
		//do nothing
		return null;
	}

	jsonMap['id'] = '' + c_id;
	jsonMap['version'] = ALINK_VERSION;

	log("finished: " + JSON.stringify(jsonMap));
	log('------------------------ rawDataToProtocol end ------------------------');
  	return jsonMap;
}

function log(){
    try{
        console.log.apply(console, arguments);
    } catch (e){

    }
    try{
        print.apply(print, arguments);
    } catch (e){

    }
};


////////////////////////////////////////////////////////////////////////////////////////////////////////////
function type_uint8(dv, offset) { return {"value":dv.getUint8(offset), "length":1};}
function type_int8(dv, offset) { return {"value":dv.getInt8(offset), "length":1};}
function type_uint16(dv, offset) { return {"value":dv.getUint16(offset), "length":2};}
function type_int16(dv, offset) { return {"value":dv.getInt16(offset), "length":2};}
function type_int32(dv, offset) { return {"value":dv.getInt32(offset), "length":4};}
function type_uint32(dv, offset) { return {"value":dv.getUint32(offset), "length":4};}
function type_int64(dv, offset)
{
  var low = dv.getUint32(offset + 4);
  var n = dv.getUint32(offset) * 4294967296.0 + low;
  if (low < 0) n += 4294967296;
  return {"value":n, "length":8};
}
function type_uint64(dv, offset)
{
  var low = dv.getUint32(offset + 4);
  var n = dv.getUint32(offset) * 4294967296.0 + low;
  if (low < 0) n += 4294967296;
  return {"value":n, "length":8};
}

function type_float(dv, offset) 
{
	 return {"value":dv.getFloat32(offset), "length":4};
}
function type_double(dv, offset) 
{
	 return {"value":dv.getFloat64(offset), "length":8};
}
function type_string(bytes, offset, length)
{
	var value = String.fromCharCode.apply(null, bytes.subarray(offset, offset + length));
	var endIndex = value.indexOf('\u0000', 0);
	if (endIndex >= 0)
	  value = value.substr(0, endIndex);

	return {"value":value, "length":length};
}

// [typeID -> byte] [attrID -> byte] [value -> dynamic]
// [typeID -> byte] [attrID -> byte] [length -> int16] [value -> dynamic]

function type_dynamic_with_param(bytes, dataview, offset, typeID, precise)
{
	var tmpOffset = offset;
	var value = null, v = 0;
	if (typeID == PP_TYPE.PROTOCOL_PROP_TYPE_BOOL)
	{
		v = type_uint8(dataview, tmpOffset);
		tmpOffset += v.length;
		value = v.value;
	}
	else if (typeID == PP_TYPE.PROTOCOL_PROP_TYPE_INT8)
	{
		v = type_int8(dataview, tmpOffset);
		tmpOffset += v.length;
		value = v.value;
	}
	else if (typeID == PP_TYPE.PROTOCOL_PROP_TYPE_UINT8)
	{
		v = type_uint8(dataview, tmpOffset);
		tmpOffset += v.length;
		value = v.value;
	}
	else if (typeID == PP_TYPE.PROTOCOL_PROP_TYPE_INT16)
	{
		v = type_int16(dataview, tmpOffset);
		tmpOffset += v.length;
		value = v.value;
	}
	else if (typeID == PP_TYPE.PROTOCOL_PROP_TYPE_UINT16)
	{
		v = type_uint16(dataview, tmpOffset);
		tmpOffset += v.length;
		value = v.value;
	}
	else if (typeID == PP_TYPE.PROTOCOL_PROP_TYPE_INT32)
	{
		v = type_int32(dataview, tmpOffset);
		tmpOffset += v.length;
		value = v.value;
	}
	else if (typeID == PP_TYPE.PROTOCOL_PROP_TYPE_UINT32)
	{
		v = type_uint32(dataview, tmpOffset);
		tmpOffset += v.length;
		value = v.value;
	}
	else if (typeID == PP_TYPE.PROTOCOL_PROP_TYPE_FLOAT32)
	{
		v = type_float(dataview, tmpOffset);
		tmpOffset += v.length;
		value = parseFloat(v.value.toFixed(precise));
	}
	else if (typeID == PP_TYPE.PROTOCOL_PROP_TYPE_FLOAT64)
	{
		v = type_double(dataview, tmpOffset);
		tmpOffset += v.length;
		value = parseFloat(v.value.toFixed(precise));
	}
	else if (typeID == PP_TYPE.PROTOCOL_PROP_TYPE_STRING)
	{
		var strLength = type_int16(dataview, tmpOffset);
		tmpOffset += strLength.length;

		var string_v = type_string(bytes, tmpOffset, strLength.value);
		value = string_v.value;
		tmpOffset += string_v.length;
	}
	else if (typeID == PP_TYPE.PROTOCOL_PROP_TYPE_INT64)
	{
		var timestamp_v = type_int64(dataview, tmpOffset);
		tmpOffset += timestamp_v.length;
		value = timestamp_v.value;
	}
	else if (typeID == PP_TYPE.PROTOCOL_PROP_TYPE_UINT64)
	{
		var timestamp_v = type_uint64(dataview, tmpOffset);
		tmpOffset += timestamp_v.length;
		value = timestamp_v.value;
	}
	else if (typeID == PP_TYPE.PROTOCOL_PROP_TYPE_DATE)
	{
		var date_v = type_uint64(dataview, tmpOffset);
		tmpOffset += date_v.length;
		value = date_v.value.toString();
	}

	return {"value":value, "length":tmpOffset - offset};
}

function type_dynamic(bytes, dataview, offset)
{
    var tmpOffset = new Number(offset);
    var typeID = bytes[tmpOffset++];
	var attrID = bytes[tmpOffset++];

	/* 结构体解析 */
	if (typeID >= structStartId)
	{
		var structVal = {}, structSize = 0;
		var structName = g_structArray[typeID - structStartId];
		var structMemb = g_structDataMap[structName];
		var itemData = structMemb.item;
		var itemArray = structMemb.itemArray;

		for (var i = 0; i < itemArray.length; i++) 
		{
			var elemName = itemArray[i];
			var item = itemData[elemName];
			var type = item.protocolType;

			/* string固定字节 */
			if (type == PP_TYPE.PROTOCOL_PROP_TYPE_STRING)
			{
				var string_v = type_string(bytes, tmpOffset + structSize, item.size);
				structVal[elemName] = string_v.value;
				structSize += item.size;
			}
			else
			{
				var payloadObj = type_dynamic_with_param(bytes, dataview, tmpOffset + structSize, type, item.precise);
				if (item.v2s)
				{
					structVal[elemName] = payloadObj.value.toString();
				}
				else if (type >= PP_TYPE.PROTOCOL_PROP_TYPE_BOOL && type <= PP_TYPE.PROTOCOL_PROP_TYPE_UINT64)
				{
					structVal[elemName] = parseInt(payloadObj.value.toString());
				}
				else
				{
					structVal[elemName] = payloadObj.value;
				}
				structSize += payloadObj['length'];
			}
		}

		return {"value":structVal, "length":(2 + structSize), attrID:attrID};
	}

	var precise = 0;
	var attrName = g_attrAry[attrID];
	var attrItem = g_attrTypeMap[attrName];
	if (typeID == PP_TYPE.PROTOCOL_PROP_TYPE_FLOAT32 || typeID == PP_TYPE.PROTOCOL_PROP_TYPE_FLOAT64)
	{
		precise = attrItem.precise;
	}
	var v = type_dynamic_with_param(bytes, dataview, tmpOffset, typeID, precise);
	if (attrItem.v2s)
	{
		return {"value":v.value.toString(), "length":(2 + v.length), attrID:attrID};
	}
	else if (typeID >= PP_TYPE.PROTOCOL_PROP_TYPE_BOOL && typeID <= PP_TYPE.PROTOCOL_PROP_TYPE_UINT64)
	{
		return {"value":parseInt(v.value.toString()), "length":(2 + v.length), attrID:attrID};
	}
	else
	{
		return {"value":v.value, "length":(2 + v.length), attrID:attrID};
	}
}

function buffer_uint8(value)
{
    var uint8Array = new Uint8Array(1);
    var dv = new DataView(uint8Array.buffer, 0);
    dv.setUint8(0, value);
    return [].slice.call(uint8Array);
}
function buffer_int8(value)
{
    var uint8Array = new Uint8Array(1);
    var dv = new DataView(uint8Array.buffer, 0);
    dv.setInt8(0, value);
    return [].slice.call(uint8Array);
}
function buffer_int16(value)
{
    var uint8Array = new Uint8Array(2);
    var dv = new DataView(uint8Array.buffer, 0);
    dv.setInt16(0, value);
    return [].slice.call(uint8Array);
}
function buffer_uint16(value)
{
    var uint8Array = new Uint8Array(2);
    var dv = new DataView(uint8Array.buffer, 0);
    dv.setUint16(0, value);
    return [].slice.call(uint8Array);
}
function buffer_uint32(value)
{
    var uint8Array = new Uint8Array(4);
    var dv = new DataView(uint8Array.buffer, 0);
    dv.setUint32(0, value);
    return [].slice.call(uint8Array);
}
function buffer_int32(value)
{
    var uint8Array = new Uint8Array(4);
    var dv = new DataView(uint8Array.buffer, 0);
    dv.setInt32(0, value);
    return [].slice.call(uint8Array);
}
function buffer_int64(value)
{
    //Number.MAX_SAFE_INTEGER
    var local_MAX_UINT32 = 0xFFFFFFFF;
    var big = ~~(value / local_MAX_UINT32);
    var low = (value % local_MAX_UINT32) - big;
    var uint8Array = new Uint8Array(8);
    var dv = new DataView(uint8Array.buffer, 0);
	  dv.setInt32(0, big);
	  dv.setInt32(4, low);
    return [].slice.call(uint8Array);
}
function buffer_uint64(value)
{
    //Number.MAX_SAFE_INTEGER
    var local_MAX_UINT32 = 0xFFFFFFFF;
    var big = ~~(value / local_MAX_UINT32);
    var low = (value % local_MAX_UINT32) - big;
    var uint8Array = new Uint8Array(8);
    var dv = new DataView(uint8Array.buffer, 0);
    dv.setUint32(0, big);
    dv.setUint32(4, low);
    return [].slice.call(uint8Array);
}
function buffer_float(value)
{
    var uint8Array = new Uint8Array(4);
    var dv = new DataView(uint8Array.buffer, 0);
    dv.setFloat32(0, value);
    return [].slice.call(uint8Array);
}
function buffer_double(value)
{
    var uint8Array = new Uint8Array(8);
    var dv = new DataView(uint8Array.buffer, 0);
    dv.setFloat64(0, value);
    return [].slice.call(uint8Array);
}
function buffer_string(value)
{
    var string = unescape(encodeURIComponent(value));
    var charList = string.split('');
    var uint8Array = new Array();
    for (var i = 0; i < charList.length; i++) {
        uint8Array.push(charList[i].charCodeAt(0));
    }
    var byteLength = uint8Array.length;
    return [].concat(buffer_int16(byteLength), uint8Array);
}
function buffer_dynamic(value, typeID)
{
	if (typeID == PP_TYPE.PROTOCOL_PROP_TYPE_BOOL)
	{
		return buffer_uint8(value);
	}
	else if (typeID == PP_TYPE.PROTOCOL_PROP_TYPE_INT8)
	{
		return buffer_int8(value);
	}
	else if (typeID == PP_TYPE.PROTOCOL_PROP_TYPE_UINT8)
	{
		return buffer_uint8(value);
	}
	else if (typeID == PP_TYPE.PROTOCOL_PROP_TYPE_INT16)
	{
		return buffer_int16(value);
	}
	else if (typeID == PP_TYPE.PROTOCOL_PROP_TYPE_UINT16)
	{
		return buffer_uint16(value);
	}
	else if (typeID == PP_TYPE.PROTOCOL_PROP_TYPE_INT32)
	{
		return buffer_int32(value);
	}
	else if (typeID == PP_TYPE.PROTOCOL_PROP_TYPE_UINT32)
	{
		return buffer_uint32(value);
	}
	else if (typeID == PP_TYPE.PROTOCOL_PROP_TYPE_INT64)
	{
		return buffer_int64(value);
	}
	else if ((typeID == PP_TYPE.PROTOCOL_PROP_TYPE_UINT64)
			|| (typeID == PP_TYPE.PROTOCOL_PROP_TYPE_DATE))
	{
		return buffer_uint64(value);
	}
	else if (typeID == PP_TYPE.PROTOCOL_PROP_TYPE_FLOAT32)
	{
		return buffer_float(value);
	}
	else if (typeID == PP_TYPE.PROTOCOL_PROP_TYPE_FLOAT64)
	{
		return buffer_double(value);
	}
	else if (typeID == PP_TYPE.PROTOCOL_PROP_TYPE_STRING)
	{
		return buffer_string(value);
	}
}

//本地server环境中使用， 上传到服务端时可以把以下代码删掉
if (typeof exports !== "undefined")
{
    exports.rawDataToProtocol = rawDataToProtocol;
    exports.protocolToRawData = protocolToRawData;
}